home *** CD-ROM | disk | FTP | other *** search
- /*
- * (c) Copyright 1993 by Panagiotis Tsirigotis
- * All rights reserved. The file named COPYRIGHT specifies the terms
- * and conditions for redistribution.
- */
-
- static char RCSid[] = "$Id: timer.c,v 4.2 1993/05/06 06:43:14 panos Exp $" ;
- static char *version = VERSION ;
-
- #include "timemacros.h"
- #include "impl.h"
- #include "defs.h"
-
- #define TIMER_H_NULL ((timer_h)NULL)
-
-
- int timer_errno ;
-
-
-
- /*
- * Create a timer of the specified type.
- * Returns a timer handle
- */
- timer_h timer_create( type, flags, errnop )
- enum timer_types type ;
- int flags ;
- int *errnop ;
- {
- int *errp = ( errnop != NULL ) ? errnop : &timer_errno ;
- timer_s *tp ;
-
- if ( type != TIMER_REAL && type != TIMER_VIRTUAL && type != TIMER_PROF )
- HANDLE_ERROR( flags, TIMER_H_NULL, errp, TIMER_EBADTYPE,
- "TIMER timer_create: bad timer type\n" ) ;
-
- tp = TIMER_ALLOC() ;
- if ( tp == NULL )
- {
- *errp = TIMER_ENOMEM ;
- return( TIMER_H_NULL ) ;
- }
-
- tp->t_state = INACTIVE ;
- tp->t_act = IDLE ;
- tp->t_blocked = FALSE ;
-
- tp->t_errnop = errp ;
- tp->t_flags = flags & TIMER_CREATE_FLAGS ;
- tp->t_action.ta_func = NULL ;
- tp->t_action.ta_arg = NULL ;
- tp->t_action.ta_flags = TIMER_NOFLAGS ;
- if ( __ostimer_newtimer( tp, type ) == TIMER_ERR )
- {
- TIMER_FREE( tp ) ;
- return( TIMER_H_NULL ) ;
- }
- return( (timer_h) tp ) ;
- }
-
-
- void timer_destroy( handle )
- timer_h handle ;
- {
- timer_s *tp = TP( handle ) ;
-
- __ostimer_blockall() ;
-
- if ( tp->t_state == TICKING )
- {
- __ostimer_remove( tp->t_ostimer, tp ) ;
- tp->t_state = DESTROYED ;
- }
-
- if ( tp->t_act == IDLE || tp->t_act == PENDING )
- TIMER_FREE( tp ) ;
-
- __ostimer_unblockall() ;
- }
-
-
- int timer_start( handle, itvp, time_type, ap )
- timer_h handle ;
- struct itimerval *itvp ;
- enum timer_timetypes time_type ;
- struct timer_action *ap ;
- {
- int result ;
- int ok_to_start ;
- timer_s *tp = TP( handle ) ;
- struct os_timer *otp = tp->t_ostimer ;
-
- __ostimer_blockall() ;
-
- /*
- * We allow invoking timer_start from within the user-specified action
- * after the timer has expired. However, we do not allow this for
- * timers that have a t_interval (these timers stay at the TICKING state).
- */
- ok_to_start = tp->t_state == INACTIVE &&
- ( tp->t_act == IDLE || tp->t_act == INVOKED ) ;
-
- if ( ! ok_to_start )
- {
- __ostimer_unblockall() ;
- HANDLE_ERROR( tp->t_flags, TIMER_ERR, tp->t_errnop, TIMER_EBADSTATE,
- "TIMER timer_start: timer state does not allow this operation\n" ) ;
- }
-
- if ( itvp->it_value.tv_sec < 0 || itvp->it_value.tv_usec < 0 )
- {
- __ostimer_unblockall() ;
- HANDLE_ERROR( tp->t_flags, TIMER_ERR, tp->t_errnop, TIMER_EBADTIME,
- "TIMER timer_start: neg time value)\n" ) ;
- }
-
- tp->t_action = *ap ;
- tp->t_action.ta_flags &= TIMER_START_FLAGS ;
-
- result = __ostimer_add( otp, tp, itvp, time_type ) ;
- __ostimer_unblockall() ;
- return( result ) ;
- }
-
-
- void timer_stop( handle )
- timer_h handle ;
- {
- timer_s *tp = TP( handle ) ;
-
- __ostimer_blockall() ;
-
- if ( tp->t_state == TICKING )
- {
- __ostimer_remove( tp->t_ostimer, tp ) ;
- tp->t_state = INACTIVE ;
- }
-
- if ( tp->t_act == SCHEDULED )
- tp->t_act = INVOKED ; /* to avoid the invocation */
- else if ( tp->t_act == PENDING )
- tp->t_act = IDLE ;
-
- tp->t_blocked = FALSE ;
-
- __ostimer_unblockall() ;
- }
-
-
- void timer_block( handle )
- timer_h handle ;
- {
- timer_s *tp = TP( handle ) ;
-
- __ostimer_blockall() ;
-
- if ( tp->t_state == TICKING ||
- tp->t_state == INACTIVE &&
- ( tp->t_act == PENDING || tp->t_act == SCHEDULED ) )
- tp->t_blocked = TRUE ;
-
- __ostimer_unblockall() ;
- }
-
-
- void timer_unblock( handle )
- timer_h handle ;
- {
- timer_s *tp = TP( handle ) ;
-
- __ostimer_blockall() ;
-
- if ( tp->t_blocked )
- {
- tp->t_blocked = FALSE ;
- if ( tp->t_act == PENDING )
- {
- tp->t_act = SCHEDULED ;
- (void) __timer_invoke( tp ) ;
- }
- }
-
- __ostimer_unblockall() ;
- }
-
-
- unsigned timer_expirations( handle )
- timer_h handle ;
- {
- return( TP( handle )->t_count ) ;
- }
-
-
-
- /*
- * Invoke the action of the specified timer
- * All timer interrupts should be blocked when this function is invoked
- * Returns TRUE if
- */
- enum timer_state __timer_invoke( tp )
- register timer_s *tp ;
- {
- enum timer_state state ;
-
- /*
- * The reason for the infinite loop is that the timer may reexpire
- * while its function is being invoked.
- */
- for ( ;; )
- {
- /*
- * This is the INVOKE part
- */
- if ( tp->t_blocked )
- tp->t_act = PENDING ;
- else
- {
- if ( tp->t_state != DESTROYED && tp->t_act == SCHEDULED )
- {
- void (*func)() = tp->t_action.ta_func ;
- void *arg = tp->t_action.ta_arg ;
- int flags = tp->t_action.ta_flags ;
-
- tp->t_act = INVOKED ;
- tp->t_expirations = tp->t_count ;
- tp->t_count = 0 ;
- if ( func != NULL )
- {
- int unblock_all_intrs = ! ( flags & TIMER_BLOCK_ALL ) ;
- int unblock_all_but_same_intr = ! ( flags & TIMER_BLOCK_SAME ) ;
-
- if ( unblock_all_intrs )
- __ostimer_unblockall() ;
- else if ( unblock_all_but_same_intr )
- __ostimer_unblockall_except( tp->t_ostimer ) ;
-
- (*func)( tp, arg ) ;
-
- if ( unblock_all_intrs || unblock_all_but_same_intr )
- __ostimer_blockall() ;
- }
- else if ( arg != NULL )
- {
- int *ip = (int *) arg ;
-
- if ( flags & TIMER_INC_VAR )
- *ip += tp->t_expirations ;
- else
- *ip = 1 ;
- }
- }
- }
-
- state = tp->t_state ;
-
- /*
- * This is the RETURN part
- */
- if ( tp->t_state == DESTROYED )
- TIMER_FREE( tp ) ;
- else
- {
- if ( tp->t_act == INVOKED )
- tp->t_act = IDLE ;
- else if ( tp->t_act == SCHEDULED )
- continue ;
- }
- break ;
- }
- return( state ) ;
- }
-
-